/*
 * ValueChangedMonitor.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */

package engine;

/**
 * It's is a monitor that watches for the change of an expression, 
 * and then wakes up the associated thread (and, now and then, 
 * it gets stuck, i don't jnow why...)
 */

class ValueChangeMonitor implements Monitor
{
	NameSpace ns;
	Expression target;
	BitVector lastValue, curValue;
	long lastTime;
	Object waiter;
	volatile boolean isOn;

	static final int  EVT_CHANGE  = 0x00000001,
	EVT_POSEDGE = 0x00000010,
	EVT_NEGEDGE = 0x00000100;

	int mask;

	ValueChangeMonitor(NameSpace ns, Expression target, int mask){
		this.ns = ns;
		this.target = target;
		this.mask = mask;
		lastValue = null;
		target.addMonitor(this);
		lastTime = -1;
	}

	public synchronized void trigger()
	throws InterpretTimeException
	{
		BitVector curValue = target.evaluate().getInt();
		xConsole.debug("ValueChangeMonitor: triggering");
		if ((curValue.compare(lastValue) & mask) != 0) {
			xConsole.debug("ValueChangeMonitor: waking up waiter");
			if ( Time.clk2() > lastTime ){
				synchronized(waiter) {
					isOn = true;
					waiter.notifyAll();
				}
			}
		}
	}

	synchronized void attach(Object semaphore){
		this.waiter = semaphore;
	}

	synchronized void consume() {
		if (isOn) {
			isOn = false;
			lastValue = curValue;
			lastTime = Time.clk2();
		}
	}
	synchronized void detach(){
		waiter = null;
		isOn = false;
		lastValue = curValue;
		lastTime = Time.clk2();
	}

	boolean isTriggd(){
		return isOn;
	}

	public String toString(){
		String result = " ";
		if((mask & EVT_POSEDGE) != 0) result = "posedge ";
		else if((mask & EVT_NEGEDGE) != 0) result = "negedge ";
		result += target;
		return result;
	}

}

